package featuresWindows;

import helpFeaturesWindows.HelpStepWindow;
import j3d.J3D;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import CAD.MainFrame;

import operationSolids.CSGSolid;
import operationSolids.CompoundSolid;

import features.Block;
import features.Feature;
import features.Step;
import featuresWindows.CreateSlot.SlotDinamicBottomPanel;
import featuresWindows.CreateSlot.SlotDinamicTopPanel;

import visualCAD.holeWindowView;
import visualCAD.stepWindowView;

public class CreateStep extends stepWindowView implements ActionListener{

	private J3D j3d = null;
	private Block block = null;
	private StepDinamicTopPanel stepTopPanel;
	private StepDinamicBottomPanel stepBottomPanel;
	double  width , depth;
	int side = 0;
	Double angle=0.0;
	
	public CreateStep(J3D j3d, Block block)
	{
		super();
		setVisible(true);
		pack();
		stepSplitPanel.setDividerLocation(0.5);
		stepSplitPanel.setTopComponent(stepTopPanel=new StepDinamicTopPanel(side,width,depth,angle));
		stepSplitPanel.setBottomComponent(stepBottomPanel=new StepDinamicBottomPanel(side,width,depth,angle));
		this.j3d = j3d;
		this.block = block;
		this.init();
		
	}
	public void init()
	{
		double y = stepTopPanel.faceY;
		double x = stepTopPanel.faceX;
		double z = stepTopPanel.faceZ;
		helpButton.addActionListener(this);
		SpinnerModel depthModel = new SpinnerNumberModel(0.0,0.0, z, 0.1);
		SpinnerModel sizeModel = new SpinnerNumberModel(0.0,0.0, null, 0.1);
		stepDepthSpinner.setModel(depthModel);
		stepSizeSpinner.setModel(sizeModel);
		
		this.stepDepthSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		this.stepSizeSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		this.rotationSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		this.sideComboBox.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				redrawDynamicBoxes();
			}
		});
		
		this.submitButton.addActionListener(this);
		this.cancelButton.addActionListener(this);
		this.setResizable(false);
	}
	private void redrawDynamicBoxes(){
		try{
			side=sideComboBox.getSelectedIndex();
			width=(Double)stepSizeSpinner.getValue();
			depth=(Double)stepDepthSpinner.getValue();
			angle=(Double)rotationSpinner.getValue();
			}
			catch (Exception e1) {
				e1.printStackTrace();
				JOptionPane.showMessageDialog(null, "error in entering data");
			}
			stepSplitPanel.setDividerLocation(0.5);
			stepSplitPanel.setTopComponent(stepTopPanel=new StepDinamicTopPanel(side,width,depth,angle));
			stepSplitPanel.setBottomComponent(stepBottomPanel=new StepDinamicBottomPanel(side,width,depth,angle));
	}
	public void actionPerformed(ActionEvent evt) {
		Object origin = evt.getSource();
		
		
		if (origin.equals(this.submitButton))
		{
			this.ok();
		}
		else if (origin.equals(this.cancelButton))
		{
			this.cancel();
		}
		else if (origin.equals(this.helpButton))
		{
			new HelpStepWindow();
		}
	}
	private void cancel()
	{
		// TODO Auto-generated method stub
		this.dispose();
	}
	private void ok() 
	{
		// TODO Auto-generated method stub
		boolean ok = true;
		
	
	
		//-------------- depth Validation ---------------//
		if (ok)
		{
			try
			{
				depth = (Double)this.stepDepthSpinner.getValue();
				if(depth>stepTopPanel.faceZ){
					throw new Exception();
				}
			}
			catch (Exception e)
			{
				e.printStackTrace();
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
	
		
		if(ok){
			System.out.print(sideComboBox.getSelectedIndex());
		Step st= new Step(Feature.STEP,null,(float)width,(float)depth,sideComboBox.getSelectedIndex(),this.nameTextField.getText(),MainFrame.Face);	
		this.j3d.removeSolid();
		this.j3d.addSolid(MainFrame.block.block);
		this.dispose();
		}
	}
	
	
	class StepDinamicBottomPanel extends JComponent{
		
		Shape smallBox;
		Shape bigBox;
		Shape axisX, axisY;
		double faceX = 0;
		double faceY = 0;
		double faceZ = 0;
		double multiplier= 0;
		
		
		private void findXandY() {
			switch(MainFrame.Face){
			case MainFrame.TOPFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.length;
				faceZ = MainFrame.block.height;
				break;
			case MainFrame.LOWERFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.length;
				faceZ = MainFrame.block.height;
				break;
			case MainFrame.FRONTFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.length;
				break;
			case MainFrame.BACKFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.length;
				break;
			case MainFrame.EASTFACE:
				faceX = MainFrame.block.length;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.width;
				break;
			case MainFrame.WESTFACE:
				faceX = MainFrame.block.length;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.width;
				break;
			}
		}
		private double calculateMultiplier() {
			double multiplier = 195/faceY;
			if(faceX*multiplier > 310){
				multiplier = 310/faceX;
			}
			if(faceZ*multiplier > 180){
				multiplier = 180/faceZ;
			}
			return multiplier;
		}
		
		public StepDinamicBottomPanel(int side, double width, double depth, Double angle) {
			super();
			findXandY();
			multiplier = calculateMultiplier();
			smallBox=createBox(side,width,depth);
			bigBox=createRectangle();
			axisX = verticalLine();
			axisY = horizontalLine();
		}
		protected Shape createBox(int side, double width, double depth) {
			Shape rectangle;
			switch(side){
			case 0: rectangle = new Rectangle2D.Double(10, 20, width*multiplier, multiplier*depth); break;
			case 1: rectangle = new Rectangle2D.Double(10+(faceX*multiplier)-(width*multiplier), 20, multiplier*width, depth*multiplier); break;
			case 2: rectangle = new Rectangle2D.Double(10, 20, faceX*multiplier, multiplier*depth); break;
			case 3: rectangle = new Rectangle2D.Double(10, 20, faceX*multiplier, multiplier*depth); break;
			default: rectangle = new Rectangle2D.Double(10, 20, width*multiplier, depth);
			}
			return rectangle;
		}
		protected Shape createRectangle() {
			Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceZ*multiplier);
			return rectangle;
		}
		protected Shape verticalLine() {
			
			Shape axisY = new Line2D.Double(10, 20, 10, 50);
			return axisY;
		}
		protected Shape horizontalLine(){
			Shape axisX = new Line2D.Double(10, 20, 50, 20);
			return axisX;
		}
		
		
		public void paint(Graphics g) {
			//System.out.println("translateY = " + translateY);
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			float dash1[] = {2.5f, 2.5f};
			
			g2.setPaint(new Color(211, 211, 211));
			g2.fill(bigBox);
			g2.setPaint(new Color(135, 206, 250));
			g2.fill(smallBox);
			g2.setPaint(Color.BLUE);
			g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 
					BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f));
			g2.draw(smallBox);
			g2.setPaint(Color.BLACK);
			g2.setStroke(new BasicStroke());
			g2.draw(bigBox);
			g2.setPaint(Color.RED);
			g2.draw(axisX);
			g2.draw(axisY);
			g2.drawString("X", 50 ,20);
			g2.drawString("-Z", 0, 50);
		}
	}
	
class StepDinamicTopPanel extends JComponent{
		
		Shape smallBox;
		Shape bigBox;
		Shape axisX, axisY;
		double faceX = 0;
		double faceY = 0;
		double faceZ = 0;
		double multiplier= 0;
		
		
		private void findXandY() {
			switch(MainFrame.Face){
			case MainFrame.TOPFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.length;
				faceZ = MainFrame.block.height;
				break;
			case MainFrame.LOWERFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.length;
				faceZ = MainFrame.block.height;
				break;
			case MainFrame.FRONTFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.length;
				break;
			case MainFrame.BACKFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.length;
				break;
			case MainFrame.EASTFACE:
				faceX = MainFrame.block.length;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.width;
				break;
			case MainFrame.WESTFACE:
				faceX = MainFrame.block.length;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.width;
				break;
			}
		}
		private double calculateMultiplier() {
			double multiplier = 195/faceY;
			if(faceX*multiplier > 310){
				multiplier = 310/faceX;
			}
			if(faceZ*multiplier > 180){
				multiplier = 180/faceZ;
			}
			return multiplier;
		}
		public StepDinamicTopPanel(int side, double width, double depth, Double angle) {
			super();
			findXandY();
			multiplier = calculateMultiplier();
			smallBox=createBox(side, width, depth,angle);
			bigBox=createRectangle();
			axisX = verticalLine();
			axisY = horizontalLine();
		}
		protected Shape createBox(int side, double width, double depth,double angle) {
			Area shape=null;
			int triangleSide = 0;
			switch(side){
			case 0: triangleSide=(int) (faceY*Math.tan(Math.toRadians(angle)));break;
			case 1: triangleSide=(int) (faceY*Math.tan(Math.toRadians(angle)));break;
			case 2: triangleSide=(int) (faceX*Math.tan(Math.toRadians(angle)));break;
			case 3: triangleSide=(int) (faceX*Math.tan(Math.toRadians(angle)));break;
			}
			int rectangleSide=(int) (width-triangleSide);
			switch(side){
			case 0:
				int xp[]={(int) (rectangleSide*multiplier+10),(int) (rectangleSide*multiplier+10),(int)( multiplier*width+10)};	
				int yp[]={20,(int) (multiplier*faceY+20),(int) (multiplier*faceY+20)};
				shape= new Area(new Polygon(xp,yp,3));
				break;

			case 1:
				int xp1[]={(int) (faceX-(rectangleSide*multiplier+10)),(int) (faceX-(rectangleSide*multiplier+10)),(int)(faceX-( multiplier*width+10))};	
				int yp1[]={20,(int) (multiplier*faceY+20),(int) (multiplier*faceY+20)};
				shape= new Area(new Polygon(xp1,yp1,3));
				break;

			case 2:
				int xp2[]={(int) (rectangleSide*multiplier+10),(int) (rectangleSide*multiplier+10),(int)( multiplier*width+10)};	
				int yp2[]={20,(int) (multiplier*faceX+20),(int) (multiplier*faceX+20)};
				shape= new Area(new Polygon(xp2,yp2,3));
				break;

			case 3:
				int xp3[]={(int) (rectangleSide*multiplier+10),(int) (rectangleSide*multiplier+10),(int)( multiplier*width+10)};	
				int yp3[]={20,(int) (multiplier*faceX+20),(int) (multiplier*faceX+20)};
				shape= new Area(new Polygon(xp3,yp3,3));
				break;

			}
			Area rectangle = null;
			switch(side){
			case 0: rectangle = new Area(new Rectangle2D.Double(10, 20, rectangleSide*multiplier, multiplier*faceY)); break;
			case 1: rectangle = new Area(new Rectangle2D.Double(10+(faceX*multiplier)-(rectangleSide*multiplier), 20, width*multiplier, faceY*multiplier)); break;
			case 2: rectangle = new Area(new Rectangle2D.Double(10, 20+(faceY*multiplier)-rectangleSide*multiplier, faceX*multiplier, width*multiplier)); break;
			case 3: rectangle = new Area( new Rectangle2D.Double(10, 20, multiplier*faceX, rectangleSide*multiplier)); break;
			}
			shape.add(rectangle);
			return shape;
		}
		protected Shape createRectangle() {
			Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceY*multiplier);
			return rectangle;
		}
		protected Shape verticalLine() {
			
			Shape axisY = new Line2D.Double(10, 20, 10, 50);
			return axisY;
		}
		protected Shape horizontalLine(){
			Shape axisX = new Line2D.Double(10, 20, 50, 20);
			return axisX;
		}
		
		
		public void paint(Graphics g) {
			//System.out.println("translateY = " + translateY);
			Graphics2D g2 = (Graphics2D) g;
			g2.scale(1, -1);
			g2.translate(0, -235);
			g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			
			g2.setPaint(new Color(211, 211, 211));
			g2.fill(bigBox);
			g2.setPaint(new Color(135, 206, 250));
			g2.fill(smallBox);
			g2.setPaint(Color.BLUE);
			g2.draw(smallBox);
			g2.setPaint(Color.BLACK);
			g2.draw(bigBox);
			g2.setPaint(Color.RED);
			g2.draw(axisX);
			g2.draw(axisY);
			g2.scale(1, -1);
			g2.drawString("X", 50 ,-10);
			g2.drawString("Y", 0, -50);
		}
	}
}
